/** 引入栈和队列的库**/
#include <iostream>
#include <queue>
#include <stack>
#include <string>
#include <cstdlib>
#include <cmath>

/** 定义一个错误处理函数，当输入有问题时用于表明错误并退出运行 **/
void _err_exp()
{
        std::cerr << "Error" << std::endl;
        exit(-1);
};

/**定义一个计算后缀表达式的函数**/
 double calculate(std::queue<char>& exp)
{
	double num=0;
	int i=0;
	std::stack<double> con;
	bool flag=false;
	while (!exp.empty()) // 从左到右遍历后缀表达式的每个元素
	{
		char c=exp.front();
		if( c>='0'&&c<='9'){
			num = num*10+(c - '0'); // 将字符转换为数字
			exp.pop();//删除目前的数字，准备转换下一位
			if(flag==true){
				i++;
		}
		}
		else if(c== '.') // 处理小数点
			{
			exp.pop();
			flag=true;
			}
		else if(c==' ')// 如果遇到空格
		{
			if(num!=0){
				num=num/pow(10,i);
				con.push(num);
				num=0;
				i=0;
				flag=false;
			}
			exp.pop();
		}
		else if( c=='+'||c=='-'||c=='*'||c=='/'){
			if(num!=0){
				num=num/pow(10,i);
                                con.push(num);
                                num=0;
				i=0;
                                flag=false;
                        }       
			double num2=con.top();
			con.pop();
			double num1=con.top();
			con.pop();

			switch (c) // 根据操作符进行相应的运算
			{
				case '+':
					con.push(num1 + num2); // 执行加法运算
					break;
				case '-':
					con.push(num1 - num2); // 执行减法运算
					break;
				case '*':
					con.push(num1 * num2); // 执行乘法运算
					break;
				case '/':
					con.push(num1 / num2); // 执行除法运算
					break;
				default:
					std::cerr << "Error" << std::endl; // 操作符无效，输出错误信息
					exit(-1); // 终止程序运行
			}
			exp.pop();
		}
		else{
			_err_exp();
		}
	}
    if (con.size() != 1) // 经过上述不断运算 最后所有的数字逐渐计算得到一个数字 即唯一结果 若没有结果或循环结束仍有一个及以上的数字 则程序出错
    {
        std::cerr << "Error" << std::endl; // 输出错误信息
        exit(-1); // 终止程序运行
    }

    return con.top(); // 返回剩下的元素，即为最终计算结果
}
/** 运算符要跳过空格和制表符，小数点需要排除一次性出现多个的情况 先把运算符直接输入op 数字直接输入exp **/
int main(int argc,char* argv[]){
/** 依次输入并判断 **/
	char c;
	std::stack<char> op;    // 操作符栈
	std::queue<char> exp;   // 后缀表达式队列
	bool point = false;     // 小数点使用标志
	while(true){
		c=std::getchar();
		if(c=='\n'){break;}//当用户打出回车时，输入结束
		if(c=='\t'||c==' '){continue;}//当用户输入空格或制表符时，忽视
/**如果输入的是数字的话，直接存到队列exp中**/
		if(c>='0'&&c<='9'){
			exp.push(c);
		}
/**如果输入的是小数点，需要确保只有一个小数点，用小数点使用标志实现**/
		else if(c=='.'){
			if(point == false)// 当小数点使用标志为false时才可以将小数点读入exp
			{	exp.push(c);
				point = true;//否则后续其他浮点数将无法输入队列exp
			}else{
				_err_exp();
			} }
/**与课上的括号判断类似，此处只需考虑小括号 **/
		else if( c == ')' ){
			if(op.empty()){       
				_err_exp();
			}
/*应清空所有运算级低于它的符号*/
			while(!op.empty() && op.top()!='('){ 
				exp.push(' ');
				exp.push(op.top());
				op.pop();}//删除运算级较低的符号
			op.pop();} //删除“（ ”，因为 “）”本来就没输进去，不必删除
		else if(c=='+'||c=='-'){
			exp.push(' ');
/** + -运算级最低 所以要写到最后（除了左括号） **/
			if (!op.empty())
			{
				while (!op.empty() && op.top() != '(')
				{
					exp.push(' ');
					exp.push(op.top());
					op.pop();
				}
			}
			op.push(c);     // 写到最后面 
			/** 准备输入下一个数字，再次允许小数点**/
			point = false;
		}
		else if(c=='*'||c=='/'){//只需清空同级别的运算符
			exp.push(' ');
			if(!op.empty()){
			while(!op.empty()&&(op.top() == '*' || op.top() == '/')){
				exp.push(op.top());
				op.pop();}
			}
			op.push(c);  //前面无运算符时 可直接存入op
			point =false;}
		else if(c == '('){
			op.push(c);}
		else{
			continue;
		}
	}
	/** 输入完毕, 但操作符栈中可能还有运算符，全部输出到后缀表达式队列中**/
	if (!op.empty())
	{
		while (!op.empty()) //遍历所有残存的运算符 输入到后缀表达式中
		{
			exp.push(op.top());
			op.pop();  //删除输入过去的op.top
		}
	}
	std::queue<char> exp_new;
	/**输出后缀表达式*/
	while (!exp.empty())
	{
		std::cout << ' ' << exp.front();//依次输出 其中每个元素间的空格使得式子更明晰
		exp_new.push(exp.front());
		exp.pop(); //删掉已输出的的元素
	}
	   // 计算后缀表达式 利用calculate函数
        double result = calculate(exp_new);
	std::cout << " = "<< result << std::endl;

	return 0;
}





























